#include <stdio.h>
#include <values.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>

#include "common.h"
#include "opcodes.h"


const int ESC = '\033';


 void increment(byte & x)
{
	x = (x + 257) % 256;
}
 void decrement(byte & x)
{
	x = (x + 255) % 256;
}

void readchar(FILE *data, char &ch, status &ps)
// Read ch and check for break-in and other awkward values
{
	if (feof(data)) { ps = status::nodata; ch = ' '; return; }
	ch = getc(data);
	if (ch == ESC) ps = status::finished;
	if (ch < ' ' || feof(data)) ch = ' ';
}

int hexdigit(char ch)
// Convert CH to equivalent value
{
	if (ch >= 'a' && ch <= 'e') return(ch + 10 - 'a');
	if (ch >= 'A' && ch <= 'E') return(ch + 10 - 'A');
	if (isdigit(ch)) return(ch - '0');
	else return(0);
}

int getnumber(FILE *data, int base, status &ps)
// Read number in required base
{
    bool negative = false;
    char ch;
    int num = 0;
    do
    { readchar(data, ch, ps);
    } while (!(ch > ' ' || feof(data) || ps != status::running));
    if (ps == status::running)
    {
        if (feof(data))
        ps = status::nodata;
        else
        {
            if (ch == '-') {
                    negative = true; readchar(data, ch, ps);
            }
            else if (ch == '+') readchar(data, ch, ps);
            if (!isxdigit(ch))
                    ps = status::baddata;
            else
            {
                while (isxdigit(ch) && ps == status::running)
                {
                    if (hexdigit(ch) < base && num <= (INT32_MAX - hexdigit(ch)) / base)
                            num = base * num + hexdigit(ch);
                    else
                            ps = status::baddata;
                    readchar(data, ch, ps);
            }
        }
            }
            if (negative) num = -num;
            if (num > 0)
                    return num % 256;
            else
            return (256 - abs(num) % 256) % 256;
    }
    return 0;
}
